﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MergulhoGrafo.QuadriParticao
{
    public class ParticaoC : AbstractParticao
    {
        #region Atributos

        private List<int> arvoreT;

        #endregion

        #region Construtor

        public ParticaoC(GrafoRetangulo grafoRetangulo, ParticaoA particaoA, ParticaoB particaoB, bool A_identidade_T = false)
        {
            if (A_identidade_T)
            {
                arvoreT = GeraArvoreT_Identidade_A(grafoRetangulo, particaoA);
            }
            else
            {
                arvoreT = GeraArvoreT(grafoRetangulo, particaoA);
            }

            List<int> tempT = arvoreT;

            foreach (int indiceRetangulo in particaoB.Retangulos)
            {
                tempT.Remove(indiceRetangulo);
            }

            this.Retangulos = tempT;
        }

        #endregion

        #region Propriedades
        public List<int> T
        {
            get
            {
                return this.arvoreT;
            }
        }

        #endregion

        #region Métodos

        private List<int> GeraArvoreT_Identidade_A(GrafoRetangulo grafoRetangulo, ParticaoA particaoA)
        {
            List<int> retorno = new List<int>();

            foreach (int aresta in particaoA.Retangulos)
            {
                if (aresta % 2 == 0) //EhPar
                {
                    retorno.Add(aresta - 1);
                }
                else // EhÍmpar
                {
                    retorno.Add(aresta + 1);
                }
            }

            return retorno;
        }

        private List<int> GeraArvoreT(GrafoRetangulo grafoRetangulo, ParticaoA particaoA)
        {
            List<Retangulo> M_dual = grafoRetangulo.Dual();
            List<int> listaDeArestas = new List<int>();
            List<int> fasesVisitadas = new List<int>();
            List<int> fasesParaVisitar = new List<int>();
            fasesParaVisitar.Add(1);
            fasesVisitadas.Add(1);

            while (fasesParaVisitar.Count > 0)
            {
                int atual = fasesParaVisitar[0];
                fasesParaVisitar.RemoveAt(0);

                foreach (Retangulo ret in M_dual)
                {
                    if (!particaoA.Retangulos.Contains(ret.numeroRef))
                    {
                        if (ret.Face1 == atual)
                        {
                            if (!fasesVisitadas.Contains(ret.Face2))
                            {
                                listaDeArestas.Add(ret.numeroRef);
                                fasesParaVisitar.Add(ret.Face2);
                                fasesVisitadas.Add(ret.Face2);
                            }
                        }
                        else if (ret.Face2 == atual)
                        {
                            if (!fasesVisitadas.Contains(ret.Face1))
                            {
                                listaDeArestas.Add(ret.numeroRef);
                                fasesParaVisitar.Add(ret.Face1);
                                fasesVisitadas.Add(ret.Face1);
                            }
                        }
                    }
                }
            }
            return listaDeArestas;
        }

        public string ToStringT()
        {
            string retorno = "";

            foreach (int item in this.arvoreT)
            {
                retorno += item + " ";
            }

            return retorno;
        }

        #endregion        
    }
}
